Skip to content

feat: expandable pills and tool workflow styling from Ozwell widget - #294

Merged
garrity-miepub merged 15 commits into
mieweb:mainfrom
aditya-damerla128:feat/ai-pill-components
Aug 7, 2026
Merged

feat: expandable pills and tool workflow styling from Ozwell widget#294
garrity-miepub merged 15 commits into
mieweb:mainfrom
aditya-damerla128:feat/ai-pill-components

Conversation

@aditya-damerla128

@aditya-damerla128 aditya-damerla128 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Closes #290.

Brings the Ozwell chat widget's pill patterns into the UI package as themeable components.

What's added

  • PillSelect (src/components/PillSelect/) — the expandable option selector (the reasoning-mode capsule that expands into a segmented control). Collapsed pill → click → options → pick → collapses back. Any number of options, fully themeable via design tokens. Closes on click-outside / Escape.
pillselect-collapsed pillselect-expanded
  • ThinkingBlock (in AIMessage) — reasoning pill showing "Thinking" with a pulsing dot while streaming, then "Thought for Xs" once done. Click to expand/collapse the reasoning text.
thinking-active thinking-complete thinking-expanded
  • MCPToolCall — restyled as a status pill header + a capped-width detail box:
    • Friendly tool names with underscores stripped and tense shifted (create_patient → "Creating patient" → "Created patient").
    • Green (success) / red (error) color scheme kept the same as before.
    • Result summary and resource links always visible in the box; raw parameters toggle open/closed with a smooth animation.
  • CollapsiblePill (src/components/AI/CollapsiblePill.tsx) — shared primitive behind the thinking + tool pills.
tool-error tool-running tool-success

Checks

  • Typecheck, lint, prettier: clean
  • Tests: 15/15 pass
  • Storybook stories added/updated for all new states

All components use mieweb/ui design tokens (light + dark mode).

Copilot AI lite review requested due to automatic review settings July 1, 2026 21:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR brings Ozwell-style “pill” UI patterns into @mieweb/ui by introducing a reusable collapsible pill primitive, a new expandable PillSelect component, and updating AI message/tool-call UI to use pill-based presentation consistent with the widget.

Changes:

  • Added PillSelect component (with Storybook stories) and exported it from the package.
  • Introduced CollapsiblePill primitive and exported it from the AI barrel.
  • Restyled MCPToolCallDisplay and replaced the AI “thinking” block UI with a pill-based ThinkingBlock.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/index.ts Exports the new PillSelect component from the package entrypoint.
src/components/PillSelect/PillSelect.tsx Adds the expandable pill selector component with click-outside/Escape collapse behavior.
src/components/PillSelect/PillSelect.stories.tsx Adds Storybook coverage for default/controlled/disabled/many-options states.
src/components/PillSelect/index.ts Adds the barrel export for PillSelect types + component.
src/components/AI/MCPToolCall.tsx Refactors tool-call UI into a status pill header + details box with animated parameter reveal.
src/components/AI/index.ts Exports the new CollapsiblePill primitive from the AI module.
src/components/AI/CollapsiblePill.tsx Introduces a shared collapsible pill primitive for thinking/tool displays.
src/components/AI/AIMessage.tsx Adds the new ThinkingBlock pill behavior and swaps out the old reasoning block UI.
src/components/AI/AIMessage.stories.tsx Updates stories to cover thinking pill states (active/complete/expanded).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/components/AI/MCPToolCall.tsx Outdated
Comment thread src/components/AI/CollapsiblePill.tsx
Comment thread src/components/PillSelect/PillSelect.tsx Outdated
Comment thread src/components/PillSelect/PillSelect.tsx Outdated
Comment thread src/components/AI/CollapsiblePill.tsx Outdated
Comment thread src/components/AI/MCPToolCall.tsx Outdated
Comment thread src/components/AI/AIMessage.tsx
@aditya-damerla128
aditya-damerla128 force-pushed the feat/ai-pill-components branch from 23736c9 to 45407e5 Compare July 2, 2026 19:41
Copilot AI review requested due to automatic review settings July 16, 2026 21:46
@aditya-damerla128
aditya-damerla128 force-pushed the feat/ai-pill-components branch from 45407e5 to be25404 Compare July 16, 2026 21:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Comment thread src/components/AI/CollapsiblePill.tsx
Comment thread src/components/AI/MCPToolCall.tsx Outdated
Comment thread src/components/AI/MCPToolCall.tsx
Comment thread src/components/AI/MCPToolCall.stories.tsx
Copilot AI review requested due to automatic review settings July 17, 2026 18:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Comment thread src/components/AI/CollapsiblePill.tsx
Comment thread src/tailwind-preset.ts
Comment thread src/components/PillSelect/PillSelect.tsx
Comment thread src/components/PillSelect/PillSelect.tsx Outdated
Comment thread src/components/PillSelect/PillSelect.tsx Outdated
Comment thread src/components/AI/MCPToolCall.tsx Outdated
Copilot AI review requested due to automatic review settings July 17, 2026 19:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comment thread src/components/PillSelect/PillSelect.tsx Outdated
Copilot AI review requested due to automatic review settings July 20, 2026 15:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Comment thread src/components/PillSelect/PillSelect.tsx Outdated
Comment thread src/components/PillSelect/PillSelect.tsx Outdated
Comment thread src/components/AI/CollapsiblePill.tsx
Copilot AI review requested due to automatic review settings July 20, 2026 19:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/components/PillSelect/PillSelect.tsx:49

  • When the collapsed trigger is clicked, the focused <button> is unmounted and replaced by the expanded option buttons. Without moving focus, keyboard users can lose focus (often ending up on document.body) and have to tab around to find the options. Add a small effect to focus the selected (or first enabled) option when expanding.
  useClickOutside(ref, () => setExpanded(false), expanded);
  useEscapeKey(() => setExpanded(false), expanded);

Comment thread src/components/AI/MCPToolCall.tsx
Copilot AI review requested due to automatic review settings July 20, 2026 20:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Comment thread src/tailwind-preset.ts
Comment thread src/components/AI/AIMessage.tsx
Comment thread src/components/AI/AIMessage.tsx Outdated
Copilot AI review requested due to automatic review settings July 20, 2026 21:15
@aditya-damerla128
aditya-damerla128 force-pushed the feat/ai-pill-components branch from 4ec868f to d7f5718 Compare July 20, 2026 21:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/components/PillSelect/PillSelect.tsx:50

  • When the collapsed trigger button is activated, it’s immediately removed from the DOM and replaced with the expanded button list. This causes focus to be lost (especially for keyboard users), making the control hard to use without a mouse. Consider moving focus into the expanded options on open, and restoring focus to the collapsed trigger on close (without focusing anything on initial mount).
  const [expanded, setExpanded] = React.useState(false);
  const ref = React.useRef<HTMLDivElement>(null);

  const value = controlledValue !== undefined ? controlledValue : internalValue;
  const selectedOption = options.find((o) => o.value === value);

  useClickOutside(ref, () => setExpanded(false), expanded);
  useEscapeKey(() => setExpanded(false), expanded);

Comment thread src/components/AI/CollapsiblePill.tsx
Copilot AI review requested due to automatic review settings July 20, 2026 21:24
aditya-damerla128 and others added 12 commits August 7, 2026 10:15
- MCPToolCall: default shows only the status pill; clicking it reveals the
  whole box (result, links, raw params) in one click with a "Show details"
  tooltip. Input summary now rides in the pill while running
  ("Creating patient · John Smith"); success shows duration instead.
- Add `hidden` prop to turn the tool-call display off entirely (mirrors the
  Ozwell widget debug flag).
- tailwind-preset: safelist the AI pill arbitrary utilities, the violet
  thinking-pill classes, and the green/red status pill colors so Tailwind 3
  consumers get them.
- CollapsiblePill: don't mutate internal state when controlled; add optional
  title (tooltip).
- PillSelect: no trailing colon when empty; disable the pill when there are
  no options.
- Stories: add PillOnly and Hidden; refresh control docs.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 7, 2026 14:41
@aditya-damerla128
aditya-damerla128 force-pushed the feat/ai-pill-components branch from 7d4bd11 to 8f154a6 Compare August 7, 2026 14:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/components/PillSelect/PillSelect.tsx:80

  • Menu positioning can compute a negative left when menuWidth exceeds the available viewport width. left is clamped using menuWidth, but CSS later applies maxWidth, so the actual rendered width can be smaller than the value used for clamping, causing the popup to shift off-screen on narrow viewports.

Clamp using the effective width (min(menuWidth, maxWidth)) and also clamp minWidth so it never exceeds maxWidth.

    const maxWidth = Math.max(window.innerWidth - viewportPadding * 2, 0);
    const left = Math.min(
      Math.max(rect.left, viewportPadding),
      window.innerWidth - menuWidth - viewportPadding
    );

src/components/PillSelect/PillSelect.tsx:172

  • PillSelect exposes role="listbox"/role="option" semantics, but it doesn't implement expected listbox keyboard interactions (ArrowUp/ArrowDown/Home/End navigation). Without this, assistive tech users can get a listbox that only works via Tab, which is inconsistent with the ARIA listbox pattern.

Either remove the listbox roles and treat these as plain buttons, or add minimal arrow-key navigation that moves focus among enabled options.

          <div
            ref={menuRef}
            id={listboxId}
            role="listbox"
            aria-label={label ? `${label} options` : 'Options'}

@aditya-damerla128

Copy link
Copy Markdown
Contributor Author

@garrity-miepub i have rebased it as well, the only thing it requires is 2 approving reviewers, and i do not have access to add another reviewer, so if you can add someone to review we can move towards merging this in

@garrity-miepub

Copy link
Copy Markdown
Collaborator

@garrity-miepub i have rebased it as well, the only thing it requires is 2 approving reviewers, and i do not have access to add another reviewer, so if you can add someone to review we can move towards merging this in

@aditya-damerla128 I had to rerun the checks and CI / Lint and Type Check failed. Give it a look and once you get it fixed up, ping me and I can get it rerun and hopefully we can get this merged for you today.

@aditya-damerla128

Copy link
Copy Markdown
Contributor Author

Sure, i will take a look at this now

@aditya-damerla128

Copy link
Copy Markdown
Contributor Author

@garrity-miepub can you try running the ci again hopefully this should have fixed it

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/components/PillSelect/PillSelect.tsx:82

  • updateMenuPosition calculates left using menuWidth even though the menu can be constrained by maxWidth. If rect.width is larger than the available viewport width, CSS will clamp the menu via maxWidth, but left will still be computed against the larger menuWidth, which can produce a negative/off-screen left value. Compute left using the effective (clamped) width and avoid minWidth exceeding maxWidth.
    const menuWidth = Math.max(rect.width, 160);
    const maxWidth = Math.max(window.innerWidth - viewportPadding * 2, 0);
    const left = Math.min(
      Math.max(rect.left, viewportPadding),
      window.innerWidth - menuWidth - viewportPadding
    );

Copilot AI review requested due to automatic review settings August 7, 2026 20:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/components/PillSelect/PillSelect.tsx:80

  • Menu positioning can place the portaled listbox partially off-screen on narrow viewports. left is computed using the unclamped menuWidth, and minWidth: rect.width can override maxWidth (when the trigger is wider than the viewport), defeating the horizontal clamp and causing overflow.
    const menuWidth = Math.max(rect.width, 160);
    const maxWidth = Math.max(window.innerWidth - viewportPadding * 2, 0);
    const left = Math.min(
      Math.max(rect.left, viewportPadding),
      window.innerWidth - menuWidth - viewportPadding
    );

@garrity-miepub
garrity-miepub merged commit f8ed6b4 into mieweb:main Aug 7, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Adding expand pills and tool workflows from Ozwell Chat widget

3 participants